package com.xlh.controller.user;

import com.google.common.collect.Lists;
import com.xlh.common.Result;
import com.xlh.common.ResultEnum;
import com.xlh.constant.UserConstant;
import com.xlh.dto.PageDTO;
import com.xlh.dto.system.ValueDTO;
import com.xlh.dto.user.UserApplicationDTO;
import com.xlh.dto.user.UserConfigDTO;
import com.xlh.dto.user.UserInfoDTO;
import com.xlh.enums.ExcelTemplateEnum;
import com.xlh.enums.PermissionEnum;
import com.xlh.enums.SystemConfigEnum;
import com.xlh.enums.user.IdentityEnum;
import com.xlh.enums.user.RoleEnum;
import com.xlh.enums.user.UserStatusEnum;
import com.xlh.exception.common.GlobalException;
import com.xlh.exception.common.NotFoundException;
import com.xlh.param.user.*;
import com.xlh.pojo.system.Permission;
import com.xlh.pojo.user.User;
import com.xlh.security.UserInfoHolder;
import com.xlh.service.ExcelService;
import com.xlh.service.course.CourseService;
import com.xlh.service.system.SystemConfigService;
import com.xlh.service.user.UserService;
import com.xlh.util.ExcelsUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户
 * <p>
 * Created by lx on 2019/1/25.
 */
@Api(tags = "UserController", description = "用户")
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private UserService userService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private ExcelService excelService;

    @Autowired
    private CourseService courseService;

    @ApiOperation("获取当前登录人的用户信息")
    @GetMapping("/info")
    @PreAuthorize("permitAll()")
    public Result<UserInfoDTO> getUserInfo() {
        return Result.success(userService.getUserInfo(userInfoHolder.getUserId(), null));
    }

    @ApiOperation("修改当前登录人的信息")
    @PutMapping("/info")
    @PreAuthorize("permitAll()")
    public Result updateUserInfo(
            @RequestBody @ApiParam(value = "修改的参数", required = true) @Valid UpdateUserInfoParam param) {
        userService.updateUserInfo(userInfoHolder.getUserId(), param);
        return Result.success();
    }

    @ApiOperation("修改用户密码")
    @PutMapping("/password")
    @PreAuthorize("permitAll()")
    public Result updateUserPassword(
            @RequestBody @ApiParam(value = "修改的参数", required = true) @Valid UpdateUserPwdParam param) {
        userService.updateUserPassword(userInfoHolder.getUserId(), param.getOldPassword(), param.getNewPassword());
        return Result.success();
    }

    @ApiOperation("获取教师或管理员列表分页")
    @GetMapping("/page")
    @PreAuthorize("@permissionValidator.isAdmin()")
    public Result<PageDTO<UserInfoDTO>> listTeacherByPage(
            @RequestParam(required = false, defaultValue = "1") @ApiParam(value = "页数") Integer pageNum,
            @RequestParam(required = false, defaultValue = "10") @ApiParam(value = "每页显示条数") Integer pageSize,
            @RequestParam(required = false) @ApiParam(value = "教师信息") String userInfo,
            @RequestParam(required = false) @ApiParam(value = "角色") String roleName,
            @RequestParam @ApiParam(value = "导航类型 1：教师 3：管理员", required = true) Integer identity) {
        return Result.success(userService.listUserByPage(pageNum, pageSize, userInfo,
                RoleEnum.getByName(roleName), IdentityEnum.getByCode(identity)));
    }

    @ApiOperation("获取助教师列表分页")
    @GetMapping("/OtherTeacherPage")
    @PreAuthorize("@permissionValidator.isTeacher()")
    public Result<PageDTO<UserInfoDTO>> listOtherTeacherByPage(
            @RequestParam(required = false, defaultValue = "1") @ApiParam(value = "页数") Integer pageNum,
            @RequestParam(required = false, defaultValue = "10") @ApiParam(value = "每页显示条数") Integer pageSize,
            @RequestParam(required = false) @ApiParam(value = "课程id") Long courseId,
            @RequestParam(required = false) @ApiParam(value = "教师信息") String userInfo) {
        return Result.success(userService.listUserOtherTeacherByPage(pageNum, pageSize, courseId,
                userInfo));
    }

    @ApiOperation("解除授课")
    @PutMapping("/RelievingTeaching")
    @PreAuthorize("@permissionValidator.teacher")
    public Result deleteCourseTeacher(
            @RequestParam(required = false) @ApiParam(value = "userId") Integer userId,
            @RequestParam(required = false) @ApiParam(value = "courseId") Long courseId) {
        userService.RelievingTeaching(courseId, userId);
        return Result.success();
    }

    @Transactional
    @ApiOperation("添加助教")
    @PostMapping("/createAssistant")
    @PreAuthorize("@permissionValidator.teacher")
    public Result createAssistant(
            @RequestParam @ApiParam(value = "导航类型 1：教师 3：管理员", required = true) Integer identity,
            @RequestParam(required = false) @ApiParam(value = "courseId") Long courseId,
//            @RequestParam(required = false) @ApiParam(value = "classId") Long classId,
            @RequestBody @ApiParam(value = "添加的参数", required = true) @Valid CreateUserParam param
    ) {
        List<Long> userId = Lists.newArrayList();
        List<User> users = userService.listUserInfo(param.getUserNumber(), UserStatusEnum.NOT_DELETE);
        if (users != null && users.size() > 0) {
            //检查工号
            for (User user : users) {
                if ("2".equals(user.getRole().toString()) || "3".equals(user.getRole().toString()) || "4".equals(user.getRole().toString()) || "7".equals(user.getRole().toString())) {
                    throw new GlobalException("该账号已存在不能重复创建");
                }
            }
            courseService.queryCourseTeachers(courseId, users.get(0).getId());
            userId.add(users.get(0).getId());
        } else {
            userId = userService.createUser(
                    Lists.newArrayList(param), IdentityEnum.getByCode(identity),
                    null, null, null);
        }
        //添加课程助教关联关系
        userService.addAssistant(courseId, userId.get(0), null);
        // 添加教师课程体系权限
        if (Objects.equals(identity, IdentityEnum.TEACHER.getRoleCode())) {
            List<Permission> permissions = systemConfigService.queryPermission(
                    Lists.newArrayList(userInfoHolder.getUserId()), PermissionEnum.COURSE_DIRECTION_HIDE);
            List<Integer> hideIds = permissions.stream()
                    .map(Permission::getStatus).collect(Collectors.toList());
            systemConfigService.insertOrUpdatePermission(userId, hideIds, PermissionEnum.COURSE_DIRECTION_HIDE);
        }
        return Result.success();
    }

    @ApiOperation("初始化密码")
    @PutMapping("/{id}/init-password")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result initPassword(@PathVariable("id") @ApiParam(value = "用户id") Long userId) {
        userService.updateUserPassword(userId, "", UserConstant.INIT_PASSWORD);
        return Result.success();
    }

    @ApiOperation("批量删除用户")
    @PostMapping("/batch-delete")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result batchDeleteUser(
            @RequestParam @ApiParam(value = "错误提示 true：继续删除 null：没有作出决定") Boolean errorFlag,
            @RequestParam(required = false)
            @ApiParam(value = "是否修改为预置课程 true：修改 null：不修改") Boolean updatePreseted,
            @RequestParam(required = false) @ApiParam(value = "课程id") Long courseId,
            @RequestParam(required = false) @ApiParam(value = "班级id") Long classId,
            @RequestBody @ApiParam(value = "用户id集合", required = true) List<Long> userIds) {
        // 网络管理员删除：数据库真删，超管删除：数据库假删
        boolean logicDeleted = RoleEnum.INTERNET_ADMIN.getRoleCode() == userInfoHolder.getUser().getRole() ?
                false : true;

        userService.batchDeleteUser(courseId, classId, userIds, logicDeleted, errorFlag, updatePreseted);
        return Result.success();
    }

    @ApiOperation("添加用户")
    @PostMapping()
    @PreAuthorize("@permissionValidator.isAdmin()")
    public Result createUser(
            @RequestParam @ApiParam(value = "导航类型 1：教师 3：管理员", required = true) Integer identity,
            @RequestBody @ApiParam(value = "添加的参数", required = true) @Valid CreateUserParam param) {

        List<Long> userIds = userService.createUser(
                Lists.newArrayList(param), IdentityEnum.getByCode(identity), null, null, null);
        if (RoleEnum.UNIVERSITY_TEACHER == RoleEnum.getByName(param.getRoleName())) {
            userService.createUniversityStudent(userIds.get(0), param.getCourseDirectionHideIds());
        }

        // 添加教师课程体系权限
        if (Objects.equals(identity, IdentityEnum.TEACHER.getRoleCode())) {
            systemConfigService.insertOrUpdatePermission(
                    userIds, param.getCourseDirectionHideIds(), PermissionEnum.COURSE_DIRECTION_HIDE);
        }

        return Result.success();
    }

    @ApiOperation("编辑用户")
    @PutMapping("/{id}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result updateUser(
            @PathVariable("id") Long userId,
            @RequestParam @ApiParam(value = "导航类型 1：教师 2:学生 3：管理员", required = true) Integer identity,
            @RequestBody @ApiParam(value = "修改的参数", required = true) @Valid UserParam param) {
        userService.updateUser(userId, param, IdentityEnum.getByCode(identity));
        return Result.success();
    }

    @ApiOperation("销户/激活")
    @PutMapping("/{id}/status")
    @PreAuthorize("hasRole('INTERNET_ADMIN')")
    public Result updateUserStatus(
            @PathVariable("id") Long userId,
            @RequestBody @ApiParam(value = "修改参数", required = true) @Valid UpdateUserStatusParam param) {
        userService.updateUserStatus(Lists.newArrayList(userId), param);
        return Result.success();
    }

    @ApiOperation("账号申请")
    @PostMapping("/application")
    @PreAuthorize("hasAnyRole('MARKET_TEACHER' , 'INTERNET_ADMIN')")
    public Result<UserApplicationDTO> createUniversityTeacher(
            @RequestBody @ApiParam(value = "添加的参数", required = true) @Valid CreateUniversityTeacherParam param) {
        // 获取配置文件信息
        Map<String, List<ValueDTO>> configMap = systemConfigService.listConfigByKey(
                Lists.newArrayList(SystemConfigEnum.PROJECT_NAME.getKey(), SystemConfigEnum.INDEX_URL.getKey()));

        // 创建用户并返回用户信息
        UserApplicationDTO data = userService.createUniversityTeacherParam(param);
        data.setConfig(configMap);

        return Result.success(data);
    }

    @ApiOperation("下载教师模板")
    @GetMapping("/model/download/teacher")
    @PreAuthorize("@permissionValidator.isAdmin()")
    public void getExcelTeacherModel(HttpServletResponse res, HttpServletRequest req) {

        ExcelTemplateEnum excel = RoleEnum.INTERNET_ADMIN == RoleEnum.getByCode(userInfoHolder.getUser().getRole()) ?
                ExcelTemplateEnum.TEACHER_SPECIAL : ExcelTemplateEnum.TEACHER_COMMON;

        try {
            excelService.downloadExcelModel(res, req, excel.getName(), excel.getFilePath());
        } catch (Exception e) {
            throw new GlobalException("找不到指定的excel文件");
        }

    }

    @ApiOperation("下载学生模板")
    @GetMapping("/model/download/student")
    @PreAuthorize("@permissionValidator.adminOrTeacher")
    public void getExcelStudentModel(HttpServletResponse res, HttpServletRequest req,
                                     @RequestParam(required = false) Long classId,
                                     @RequestParam(required = false, defaultValue = "false") Boolean showDataFlag) {

        List<List<String>> data = Lists.newArrayList();
        if (classId != null && showDataFlag) {
            List<UserInfoDTO> infos = userService.queryClassUser(Lists.newArrayList(classId), null);
            infos.forEach(userInfoDTO -> {
                List<String> strs = Lists.newArrayList();
                strs.add(StringUtils.isNotBlank(userInfoDTO.getName()) ? userInfoDTO.getName() : "");
                strs.add(StringUtils.isNotBlank(userInfoDTO.getUserNumber()) ? userInfoDTO.getUserNumber() : "");
                strs.add(StringUtils.isNotBlank(userInfoDTO.getSexName()) ? userInfoDTO.getSexName() : "");
                strs.add(StringUtils.isNotBlank(userInfoDTO.getTelephoneNumber()) ?
                        userInfoDTO.getTelephoneNumber() : "");
                strs.add(StringUtils.isNotBlank(userInfoDTO.getEmail()) ? userInfoDTO.getEmail() : "");
                data.add(strs);
            });
        }

        ExcelTemplateEnum excelEnum = ExcelTemplateEnum.STUDENT_COMMON;
        try {
            excelService.downloadExcelData(res, req, excelEnum.getName(), excelEnum.getFilePath(), data, 3);
        } catch (Exception e) {
            throw new GlobalException("找不到指定的excel文件");
        }

    }

    @ApiOperation("下载学生模板")
    @GetMapping("/model/download/studentInfo")
    @PreAuthorize("@permissionValidator.adminOrTeacher")
    public void getStudentInfo(HttpServletResponse res, HttpServletRequest req,
                                     @RequestParam(required = false) Long classId,
                                     @RequestParam(required = false, defaultValue = "false") Boolean showDataFlag) {

        List<List<String>> data = Lists.newArrayList();
        if (classId != null && showDataFlag) {
            List<UserInfoDTO> infos = userService.queryClassUser(Lists.newArrayList(classId), null);
            infos.forEach(userInfoDTO -> {
                List<String> strs = Lists.newArrayList();
                strs.add(StringUtils.isNotBlank(userInfoDTO.getName()) ? userInfoDTO.getName() : "");
                strs.add(StringUtils.isNotBlank(userInfoDTO.getUserNumber()) ? userInfoDTO.getUserNumber() : "");
                strs.add(StringUtils.isNotBlank(userInfoDTO.getSexName()) ? userInfoDTO.getSexName() : "");
                strs.add(StringUtils.isNotBlank(userInfoDTO.getTelephoneNumber()) ?
                        userInfoDTO.getTelephoneNumber() : "");
                strs.add(StringUtils.isNotBlank(userInfoDTO.getEmail()) ? userInfoDTO.getEmail() : "");
                data.add(strs);
            });
        }
        try {
            excelService.downloadExcelData(res, "学生信息下载.xls",data, 2);
        } catch (Exception e) {
            throw new GlobalException("找不到指定的excel文件");
        }

    }





    @ApiOperation("从Excel导入教师")
    @PostMapping("/model/import")
    @PreAuthorize("@permissionValidator.isAdmin()")
    public Result importFromExcel(
            @RequestParam(value = "file") @ApiParam(value = "导入文档", required = true) MultipartFile file) {

        RoleEnum roleEnum = RoleEnum.getByCode(userInfoHolder.getUser().getRole());

        // 解析excel文件
        List<CreateUserParam> excelParams = ExcelsUtil.readExcelData(
                file, RoleEnum.ADMIN == roleEnum ?
                        UserConstant.TEACHER_COMMON_HEADER : UserConstant.TEACHER_SPECIAL_HEADER,
                2, 3, CreateUserParam.class);
        if (CollectionUtils.isEmpty(excelParams)) {
            return Result.error(ResultEnum.SERVER_ERROR, "excel暂无添加数据，请重新上传");
        }

        // 创建用户
        try {
            userService.createUser(excelParams, IdentityEnum.TEACHER, null, null, null);
        } catch (NotFoundException e) {
            return Result.error(ResultEnum.SERVER_ERROR, "excel暂无添加数据，请重新上传");
        }

        return Result.success();
    }

    @ApiOperation("从Excel读取学生信息")
    @PostMapping("/model/parse")
    @PreAuthorize("@permissionValidator.adminOrTeacher")
    public Result<List<CreateUserParam>> parseExcel(
            @RequestParam(value = "file") @ApiParam(value = "导入文档", required = true) MultipartFile file) {

        // 解析excel文件
        List<CreateUserParam> excelParams = ExcelsUtil.readExcelData(
                file, UserConstant.STUDENT_COMMON_HEADER, 2, 3, CreateUserParam.class);
        if (CollectionUtils.isEmpty(excelParams)) {
            return Result.error(ResultEnum.SERVER_ERROR, "excel暂无添加数据，请重新上传");
        }

        return Result.success(excelParams);
    }

    @ApiOperation("获取数据库已存在的学生信息")
    @PostMapping("/student/info")
//    @PreAuthorize("@permissionValidator.isTeacher()")
    public Result<UserInfoDTO> queryUserInfo(
            @RequestParam @ApiParam(value = "导航类型 1：教师 2:学生 3：管理员", required = true) Integer identity,
            @RequestBody @ApiParam(value = "查询参数", required = true) @Valid UserNumberParam param) {
        return Result.success(userService.getStudentInfo(param.getUserNumber(), identity));
    }

    @ApiOperation("获取当前用户配置信息")
    @GetMapping("/config")
    @PreAuthorize("permitAll()")
    public Result<UserConfigDTO> queryUserConfig() {
        return Result.success(userService.queryUserPermission());
    }

    @ApiOperation("修改当前用户配置信息")
    @PutMapping("/config")
    @PreAuthorize("@permissionValidator.isTeacher()")
    public Result updateUserConfig(@RequestBody @Valid UserPermissionParam userPermissionParam) {
        userService.updateUserConfig(userPermissionParam);
        return Result.success();
    }

    @ApiOperation("获取学校名称")
    @GetMapping("/schoolName")
    @PreAuthorize("@permissionValidator.isAdmin()")
    public Result<List<String>> querySchoolNames() {
        return Result.success(userService.querySchoolNames());
    }

    @ApiOperation("修改权限")
    @PostMapping("/permission")
    @PreAuthorize("@permissionValidator.isTeacher()")
    public Result updatePerimission(@RequestBody @Valid PermissionParam permissionParam) {
        userService.updatePermission(permissionParam.getObjIds(),
                PermissionEnum.getByCode(permissionParam.getCode()), permissionParam.isSwitchOn());
        return Result.success();
    }

}
